package com.apacheGzq.thread;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.apacheGzq.constant.Constants;
import com.apacheGzq.http.HttpContentType;
import com.apacheGzq.http.HttpRequest;
import com.apacheGzq.http.SimpleHttpRequestImpl;
import com.apacheGzq.pojo.HttpResponse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Set;

/**
 * Created by gaozhiqiang .
 */
public class ReadAndWriteTask implements Runnable {
    private static final Logger log = Logger.getLogger(ReadAndWriteTask.class);

    private String threadName = "ReadAndWriteTask-"+Thread.currentThread().getName();
    private SocketChannel client;

    public ReadAndWriteTask(SocketChannel client) {
        this.client = client;
    }

    private String getRealPath(String uri) {
        String realPath = "";
        if(StringUtils.isNotEmpty(uri)) {
            Set<String> keySet = Constants.CONTENTPATH_MAP.keySet();
            for(String key : keySet) {
                if(uri.startsWith(key)) {
                    realPath = Constants.CONTENTPATH_MAP.get(key) + uri.replace(key, "");
                    break;
                }
            }
        }
        return realPath;
    }


    private void execute() {
        try {
                ByteBuffer buf = ByteBuffer.allocate(Constants.BUFFERSIZE);

                String recvMsg = "";
                try {
                    while (client.read(buf) > 0) {
                        buf.flip();
                        recvMsg += Charset.forName(Constants.CHARSETNAME).newDecoder().decode(buf).toString();
                        buf.clear();
                    }
                } catch (IOException e) {
                    log.info("读取数据异常，关闭现有连接...");
                    client.close();
                    client.socket().close();
                }
                if(StringUtils.isNotEmpty(recvMsg)) {
                    log.info("receive message:\r\n"+recvMsg);
                    //HttpRequest request = new HttpRqeustParser().parse(recvMsg);
                    HttpRequest request = new SimpleHttpRequestImpl(recvMsg);
                    if(request != null) {
                        request.parserRequest(null);
                        String resPath = getRealPath(request.getRequestUri());
                        log.info("URI Path=>"+resPath);

                        HttpResponse response = new HttpResponse();
                        ByteBuffer buffer = ByteBuffer.allocate(Constants.BUFFERSIZE);
                        if(StringUtils.isEmpty(resPath)) {
                            response.setResponseStatusLine("HTTP/1.0 404 NOT FOUND");
                            client.write(ByteBuffer.wrap(response.toString().getBytes()));
                        } else {
                            File file = new File(resPath);
                            if(!file.exists()) {
                                response.setResponseStatusLine("HTTP/1.0 404 NOT FOUND");
                                client.write(ByteBuffer.wrap(response.toString().getBytes()));
                            } else {
                                String suffix = ".*";
                                int position = file.getName().indexOf(".");
                                if(position > 0) {
                                    suffix = file.getName().substring(position);
                                }
                                response.setContentType(HttpContentType.contentTypeMap.get(suffix));
                                FileInputStream fis = new FileInputStream(file);
                                response.setContentLength(fis.available());
                                client.write(ByteBuffer.wrap(response.toString().getBytes()));
                                FileChannel fc = fis.getChannel();

                                while (fc.read(buffer) != -1) {
                                    buffer.flip();

                                    while(buffer.hasRemaining()) {
                                        client.write(buffer);
                                    }

                                    buffer.clear();
                                }

                                fc.close();
                                fis.close();
                            }
                        }
                        client.close();
                        client.socket().close();
                    }

                } else {
                    log.info("receive nothing from client. ");
                    client.close();
                    client.socket().close();
                }



        } catch (IOException e) {
            log.error("从客户端读取数据异常!",e);
            try {
                client.close();
                client.socket().close();
            } catch (IOException e1) {
                log.error("关闭客户端连接异常!",e1);
            }
        }
    }

    @Override
    public void run() {
        log.info("Thread "+threadName + " start running...");
        execute();
        log.info("Thread "+threadName + " has finished");
    }
}
